Fce z C - DLL
Otázka od: Blazek Jaroslav
27. 9. 2002 15:36
Ahoj,
mam fci v Cckovskem DLL
extern "C" __declspec(dllexport) bool __fastcall MojeFce(const char *AStringIN,
char *AStringOUT);
" MojeDLL.dll >> MojeDLL.def "
LIBRARY MOJEDLL.DLL
EXPORTS
@MojeFce @1 ; MojeFce
a potrebuju ji volat v Delphi
zkousel jsem toto, ale nejak to nechodi, stale mi to hlasi ze dana fce v DLL
neni
A. function MojeFce(const AStringINr:PChar; AStringOUT:PChar):boolean; cdecl;
external 'MojeDLL.dll';
nebo
B. function MojeFce(const AStringINr:PChar; AStringOUT:array of char):boolean;
cdecl; external 'MojeDLL.dll';
nebo i druhy parametr jako " var "
nevim co mam pouzit za typ druheho parametru, jak pri deklaraci, tak pro volani
zkousel jsem pro volani
1. Buffer:array of char;
SetLength(Buffer, DELKA);
2. Buffer:array [0..DELKA] of char;
3. Buffer:string;
PChar(Buffer)
vzdy pro prislusne deklarace fce, vzdycky to proslo, ale po spusteni to
nahlasilo, ze fce v dynamicke knihovne neni, pritom toto v BCB mi funguje bez
problemu
ty retezce v pascalu s venkovni komunikaci me jednou zabijou
chtel jsem si prepsat tento svuj kod do Delphi, ale zasek jsem se na deklaraci
na typu < ukazatel na fci >, to mi nejak uchazi....
< C++ >
typedef bool __fastcall (* TMojeFce)(const char *, char *);
HINSTANCE hInst = LoadLibrary("MojeDLL.dll");
if (hInst)
{
TMojeFce MojeFce;
MojeFce = (TMojeFce)GetProcAddress(hInst,"@MojeFce");
if (MojeFce)
{
char *Buffer = new char[DELKA + 1];
try
{
if (MojeFce("Nejaky text", Buffer))
ShowMessage(Buffer);
}
__finally
{
delete []Buffer;
}
}
FreeLibrary(hInst);
}
</ C++ >
S pozdravem
Bc. Jaroslav Blazek
Access-IT Ceska Lipa
mailto:jaroslav.blazek@access-it.cz
http://www.access-it.cz
ICQ# : 133673990
+420605/813644
Odpovedá: Dalibor Toman
27. 9. 2002 16:07
>mam fci v Cckovskem DLL
>
>extern "C" __declspec(dllexport) bool __fastcall MojeFce(const char
*AStringIN, char *AStringOUT);
>" MojeDLL.dll >> MojeDLL.def "
>EXPORTS
> @MojeFce @1 ; MojeFce
>a potrebuju ji volat v Delphi
>zkousel jsem toto, ale nejak to nechodi, stale mi to hlasi ze dana
fce v DLL neni
bodejt kdyz ta funkce podle vseho neni exportovana pod jmenem ale pod
cislem (1). Bud predelat CCko aby se takova cunarna nekonala nebo v
Delphi v deklaraci pripsat prislusnou direktivu (ted nevim jetli to je
'index' nebo neco jineho.
pokud se v CC exportuje jmeno je jeste nutne zjistit jak je to s
dekoraci - ruzne kompilatory pridavaji ruzne veci kolem jmena
(podtrzitka zleva specifikace parametru za '@' zprava). Vliv na to ma
spousta veci (at ten __declspec ci *.DEF file). Je docela sranda
napsat kod ktery M$ a Borland C vyexportuje stejne (pouzitelne pro
Pascal)
>A. function MojeFce(const AStringINr:PChar;
AStringOUT:PChar):boolean; cdecl; external 'MojeDLL.dll';
>nebo
>B. function MojeFce(const AStringINr:PChar; AStringOUT:array of
char):boolean; cdecl; external 'MojeDLL.dll';
>nebo i druhy parametr jako " var "
zalezi na tom jak s tim druhym parametrem budes zachazet. Muzes
vyrobit primo nejaky typ (TBuff = Array[0..100] of Char) nebo nechat
bez typu atd
Function MojeFce(const AStringINr:Pointer : PChar; VAR AStringOUT ) :
BOOL; cdecl; external 'MojeDLL.dll index 1';
Boolean bych asi nahradil windowsim BOOL (pokud ta funkce opravdu neni
deklarovana tak aby vracela byte). Nevim si rady s __fastcall - je
treba se podivat do helpu k tomu CCku co to vlastne dela
PS: v helpu jsem nejak zminku o 'index' pri importu nenasel - taze to
mozna nepujde prelozit
>problem je zrejme v tom
>vzdy pro prislusne deklarace fce, vzdycky to proslo, ale po spusteni
to nahlasilo,
>ze fce v dynamicke knihovne neni, pritom toto v BCB mi funguje bez
problemu
viz vyse - je treba zarucit , ze export i import pouivaji stejne
jmeno/index funkce
>ty retezce v pascalu s venkovni komunikaci me jednou zabijou
u Z-termitaed stringu jde jen o buffer. Pokud se me povede
usporadat si v hlave ty ceckovsky pointry na pointry pak
to uz vetsinou neni problem
>chtel jsem si prepsat tento svuj kod do Delphi, ale zasek
>jsem se na deklaraci na typu < ukazatel na fci >, to mi nejak
uchazi....
pokus o prepis do Pascalu (bez kontroly kompilatorem)
TYPE
TMojeFunkce = Function(In : PChar; Out : Pointer) : BOOL;
Procedure UseTheFunction;
VAR
F : TMojeFunkce;
H : THandle;
buffer : array[0...1000] of Char;
begin
H := LoadLibrary('mojedll.dll');
if H = INVALID_HANDLE_VALUE then
Exit;
@F := GetProcAddress('skjutecne_jmeno_funkce');
if @F <> NIL then
begin
F('nejaky text',@buffer);
end
end;
--
pokud chces 'buffer' dynamicky alokovat pak (a bude to tedy pinter na
neco) pak volas
F('nejaky text',buffer);
Zdravi
D. Toman
Odpovedá: Ondrej Kelle
27. 9. 2002 17:11
> extern "C" __declspec(dllexport) bool __fastcall
> MojeFce(const char *AStringIN, char *AStringOUT);
> a potrebuju ji volat v Delphi
> zkousel jsem toto, ale nejak to nechodi, stale mi to hlasi ze
> dana fce v DLL neni
To znamena, ze funkcia s menom 'MojeFce' nebola v tej DLL exportovana.
C++ kompilatory maju niekedy vo zvyku menit vysledne mena funkcii (tzv. name
mangling). Skutocne mena v DLL si mozes zistit napr. pomocou tdump alebo
Dependency Walker.
V tom C++ priklade to mas dokonca uvedene v kode: '@MojeFce'
Takze:
function MojeFce(AStringIn, AStringOut: PChar): BOOL; external 'MojeDLL.dll'
name '@MojeFce';
pripadne mozes linkovat pomocou indexu:
function MojeFce(AStringIn, AStringOut: PChar): BOOL; external 'MojeDLL.dll'
index 0;
Dalej, "cdecl" nie je myslim ta spravna calling convention; ekvivalentom pre
Borland "__fastcall" je v Delphi tusim "register" (co je default).
> typedef bool __fastcall (* TMojeFce)(const char *, char *);
>
> HINSTANCE hInst = LoadLibrary("MojeDLL.dll");
> if (hInst)
> {
> TMojeFce MojeFce;
> MojeFce = (TMojeFce)GetProcAddress(hInst,"@MojeFce");
> if (MojeFce)
> {
> char *Buffer = new char[DELKA + 1];
> try
> {
> if (MojeFce("Nejaky text", Buffer))
> ShowMessage(Buffer);
> }
> __finally
> {
> delete []Buffer;
> }
> }
> FreeLibrary(hInst);
> }
type
TMojeFce = function(AStringIn, AStringOut: PChar): BOOL;
var
hInst: HINSTANCE;
MojeFce: TMojeFce;
Buffer: array[0..DELKA + 1] of Char;
begin
hInst := LoadLibrary('MojeDLL.dll');
if hInst <> 0 then
try
@MojeFce := GetProcAddress(hInst, '@MojeFce');
if @MojeFce <> nil then
if MojeFce('Nejaky text', Buffer) then
ShowMessage(Buffer);
finally
FreeLibrary(hInst);
end;
end;
HTH
TOndrej
Odpovedá: Ondrej Kelle
27. 9. 2002 17:50
> function MojeFce(AStringIn, AStringOut: PChar): BOOL;
> external 'MojeDLL.dll' name '@MojeFce';
>
> pripadne mozes linkovat pomocou indexu:
>
> function MojeFce(AStringIn, AStringOut: PChar): BOOL;
> external 'MojeDLL.dll' index 0;
Este som zabudol dopisat, nema zmysel linkovat tu DLL staticky, ked ju potom
natahujes dynamicky.
Takze tieto external deklaracie vymaz a pouzi len ten kod s
LoadLibrary/GetProcAddress.
TOndrej
Odpovedá: Petr Vones
27. 9. 2002 18:24
From: "Dalibor Toman" <dtoman@fortech.cz>
> >EXPORTS
> > @MojeFce @1 ; MojeFce
>
> bodejt kdyz ta funkce podle vseho neni exportovana pod jmenem ale pod
> cislem (1). Bud predelat CCko aby se takova cunarna nekonala nebo v
Neni to 1 spise hint ? Jinak funkce by ve Win32 mely byt exportovany zasadne
jen jmenem.
Petr Vones
Odpovedá: Blazek Jaroslav
27. 9. 2002 20:19
Ahoj,
> dtoman@fortech.cz 27.9.02 16:58 >>>
>extern "C" __declspec(dllexport) bool __fastcall MojeFce(const char
*AStringIN, char *AStringOUT);
>" MojeDLL.dll >> MojeDLL.def "
>EXPORTS
> @MojeFce @1 ; MojeFce
>bodejt kdyz ta funkce podle vseho neni exportovana pod jmenem ale pod
>cislem (1). Bud predelat CCko aby se takova cunarna nekonala nebo v
>Delphi v deklaraci pripsat prislusnou direktivu (ted nevim jetli to je
>'index' nebo neco jineho.
tak to asi ne.....ta fce tam je a jmenuje se MojeFce, v BCB ji normalne nactu
toto je vypis z utilitky impdef.exe, ktera je soucasti Borlandu
impdef.exe MojeDLL.def MojeDLL.dll
>pokud se v CC exportuje jmeno je jeste nutne zjistit jak je to s
>dekoraci - ruzne kompilatory pridavaji ruzne veci kolem jmena
>(podtrzitka zleva specifikace parametru za '@' zprava). Vliv na to ma
>spousta veci (at ten __declspec ci *.DEF file). Je docela sranda
>napsat kod ktery M$ a Borland C vyexportuje stejne (pouzitelne pro
>Pascal)
od toho tam mam < extern "C" ... > tak aby se tak nedelo
pokud bych tam mel < _export > nebo < extern "C++" >, tak ano fci budu mit
ulozenou treba takto
EXPORTS
@MojeFce$qqrpxct1pc @1 ; __fastcall MojeFce(const char *, char *)
>Nevim si rady s __fastcall - je treba se podivat do helpu k tomu CCku co to
vlastne dela
je to vlastne konverze volani fci v BCB, tudiz i rychlejsi pristup k temto
fcim, rika kompilatoru jak ma zachazet se zasobnikem
>chtel jsem si prepsat tento svuj kod do Delphi, ale zasek
>jsem se na deklaraci na typu < ukazatel na fci >, to mi nejak
uchazi....
>TYPE
> TMojeFunkce = Function(In : PChar; Out : Pointer) : BOOL;
tohle jsem nedovedl napsat, proste jako Cckari mi chybi zaklady paskalu
jen jsem to prepsal na
type
TMojeFce = function (const AStringIN : PChar; AStringOUT : PChar);
> F('nejaky text',@buffer);
jen toto bych poopravil na
var Buffer : array [0..DELKA + 1] of Char;
F(PChar('nejaky text'), Buffer);
S pozdravem
Bc. Jaroslav Blazek
Access-IT Ceska Lipa
mailto:jaroslav.blazek@access-it.cz
http://www.access-it.cz
ICQ# : 133673990
+420605/813644
Odpovedá: Blazek Jaroslav
27. 9. 2002 19:25
Ahoj,
> O.Kelle@digitalpublishing.de 27.9.02 17:06 >>>
>To znamena, ze funkcia s menom 'MojeFce' nebola v tej DLL exportovana.
>C++ kompilatory maju niekedy vo zvyku menit vysledne mena funkcii (tzv. name
>mangling). Skutocne mena v DLL si mozes zistit napr. pomocou tdump alebo
>Dependency Walker.
>V tom C++ priklade to mas dokonca uvedene v kode: '@MojeFce'
to same co jsem psal < D. Tomanovi > s < extern "C++" > a < _export >
>type
> TMojeFce = function(AStringIn, AStringOut: PChar): BOOL;
>var
> hInst: HINSTANCE;
na tohle mi nejak D5 rvalo, ze < HINSTANCE > nezna a nenalezl jsem k tomu
nejaky hlavickovy soubor, tak jsem to nahradil < LongWord >
> if MojeFce('Nejaky text', Buffer) then
take bych mozna trochu poopravil, jinak to nebere
if MojeFce(PChar('Nejaky tex'), Buffer) then
ale jinak diky vsem, uz mi to chodi pomoci dynamickeho natahnuti DLLka
S pozdravem
Bc. Jaroslav Blazek
Access-IT Ceska Lipa
mailto:jaroslav.blazek@access-it.cz
http://www.access-it.cz
ICQ# : 133673990
+420605/813644
Odpovedá: Blazek Jaroslav
27. 9. 2002 19:27
Ahoj,
> O.Kelle@digitalpublishing.de 27.9.02 17:10 >>>
>Este som zabudol dopisat, nema zmysel linkovat tu DLL staticky, ked ju potom
>natahujes dynamicky.
>Takze tieto external deklaracie vymaz a pouzi len ten kod s
>LoadLibrary/GetProcAddress.
to samozrejme ne.....ja jsem si chtel vyzkouset obe varianty, jak dynamicky,
tak staticky
S pozdravem
Bc. Jaroslav Blazek
Access-IT Ceska Lipa
mailto:jaroslav.blazek@access-it.cz
http://www.access-it.cz
ICQ# : 133673990
+420605/813644
Odpovedá: Dalibor Toman
30. 9. 2002 11:22
>> if MojeFce('Nejaky text', Buffer) then
>take bych mozna trochu poopravil, jinak to nebere
>
> if MojeFce(PChar('Nejaky tex'), Buffer) then
to by nemelo hrat roli. Kompilator vi jak s konstantnim textem
zachazet
D. Toman
Odpovedá: Dalibor Toman
30. 9. 2002 11:38
>>EXPORTS
>> @MojeFce @1 ; MojeFce
>>bodejt kdyz ta funkce podle vseho neni exportovana pod jmenem ale
pod
>>cislem (1). Bud predelat CCko aby se takova cunarna nekonala nebo v
>>Delphi v deklaraci pripsat prislusnou direktivu (ted nevim jetli to
je
>>'index' nebo neco jineho.
>
>tak to asi ne.....ta fce tam je a jmenuje se MojeFce, v BCB ji
normalne nactu
>toto je vypis z utilitky impdef.exe, ktera je soucasti Borlandu
>
>impdef.exe MojeDLL.def MojeDLL.dll
s tim indexem jsem asi nemel pravdu. Ale stejne bych se alespon text
viewerem podival na DLLko a hledal text 'MojeFce'. POkud tam nebude je
to problem. Pokud tam je nemeli by kolem nej byt podtrzitka a
zavinace. Nejjistejsi je vzit nejaky PE viewer a podivat se na jmena
exportovanych funkci. Tak zjistis presne jak to CCko exportuje. Pred
par mesicema jsem se s tim dost nazlobil (nenasel jsem zapis deklarace
exportovanych funkci pouzitelny jak pro MS C++ tak pro BC++. Nakonec
jsem, pouzil neco jako:
#ifdef __BCPLUSPLUS__
#define PPAPIENTRY _export _stdcall
#else
#define PPAPIENTRY __declspec( dllexport ) __stdcall
#endif
vlastni pouziti pak:
extern "C" HRESULT APIENTRY PPP_POP3_Scan(DWORD MessageHandle);
*.DEF file jsem nepouzil (byly s tim taky problemy, udrzba atd)
mozna to slo vyresit lip. Ale ja pro zmenu zase nejsem Cckar a
spokojil jsem se s prvnim vyhovujicim resenim..
D. Toman
Odpovedá: Dalibor Toman
30. 9. 2002 12:26
>function Fce(const AParam:string,...
>...
> MojeFce(AParam,...)
>
>tak to hazi chybu < Incompatible types : 'String' and 'PChar' >
jasne - tam je to pretypovani nutne uvest (ale opet ne v pripade, ze
te funkci predavas textovy literal)
D. Toman
Odpovedá: Blazek Jaroslav
30. 9. 2002 13:00
Ahoj,
> dtoman@fortech.cz 30.9.02 10:08 >>>
>> if MojeFce('Nejaky text', Buffer) then
>take bych mozna trochu poopravil, jinak to nebere
>
> if MojeFce(PChar('Nejaky tex'), Buffer) then
>to by nemelo hrat roli. Kompilator vi jak s konstantnim textem
>zachazet
Aha....no takhle to opravdu jde, ale jakmile mam
function Fce(const AParam:string,...
...
MojeFce(AParam,...)
tak to hazi chybu < Incompatible types : 'String' and 'PChar' >
S pozdravem
Bc. Jaroslav Blazek
Access-IT Ceska Lipa
mailto:jaroslav.blazek@access-it.cz
http://www.access-it.cz
ICQ# : 133673990
+420605/813644